/*
 * Project CelestialBeing: base_math.hpp
 * Created: 2023/12/08
 * This program uses MulanPSL2. See LICENSE for more.
 */

#ifndef CELESTIALBEING_BASE_MATH_HPP
#define CELESTIALBEING_BASE_MATH_HPP
#include <cassert>
#include <cmath>
#include "cb/common/celestial_being_base.hpp"

CB_NAMESPACE_BEGIN

template<typename T>
constexpr T Ceil (T f);

template<>
constexpr float Ceil<float> (float f)
{
    auto i = static_cast<int>(f);
    return static_cast<float>(f > i ? i + 1 : i);
}
template<>
constexpr double Ceil<double> (double f)
{
    auto i = static_cast<int64_t>(f);
    return static_cast<double>(f > i ? i + 1 : i);
}

template<typename T>
constexpr T DivideAndRoundUp (const T & a, const T & b) {
    assert(a > 0 && b > 0);
    return (a + b - 1) / b;
}
template<>
constexpr float DivideAndRoundUp<float>(const float & a, const float & b) {
    assert(a > 0 && b > 0);
    return Ceil(a / b);
}
template<>
constexpr double DivideAndRoundUp<double>(const double & a, const double & b) {
    assert(a > 0 && b > 0);
    return Ceil(a / b);
}

template<typename T>
constexpr T RoundUpToMultiplyOf(const T & a, const T & b) {
    assert(a > 0 && b > 0);
    return DivideAndRoundUp(a, b) * b;
}

template<typename T>
constexpr bool IsPowerOf2(const T & a) {
    assert(a > 0);
    return (a & (a - 1)) == 0;
}

CB_NAMESPACE_END

#endif //CELESTIALBEING_BASE_MATH_HPP
